VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "clsScoreTable"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Private Type PM_SCORE
    Name As String * 3  'The high score owner's name
    Ghosts As Long      'Number of ghosts eaten in total
    Time As Long        'Total time spent playing (in seconds)
    Score As Long       'The score they achieved
    Timestamp As Date   'The date/time the score was achieved
End Type

'Default number of enteries on a score table
Private Const PM_SCORE_LISTSIZE = 20

Public FilePath As String
Private Scores() As PM_SCORE

Public Enum PM_RANKBY
    PM_RANKBY_SCORE = 0
    PM_RANKBY_TIME = 1
End Enum

Private Sub Class_Initialize()
    'Set the size of the high score tables
    Me.Count = PM_SCORE_LISTSIZE
End Sub

Public Property Get Name(ByVal Rank As Long) As String: Name = Scores(Rank).Name: End Property
Public Property Let Name(ByVal Rank As Long, ByVal Value As String): Scores(Rank).Name = Value: End Property
Public Property Get Ghosts(ByVal Rank As Long) As Long: Ghosts = Scores(Rank).Ghosts: End Property
Public Property Let Ghosts(ByVal Rank As Long, ByVal Value As Long): Scores(Rank).Ghosts = Value: End Property
Public Property Get Time(ByVal Rank As Long) As Long: Time = Scores(Rank).Time: End Property
Public Property Let Time(ByVal Rank As Long, ByVal Value As Long): Scores(Rank).Time = Value: End Property
Public Property Get Score(ByVal Rank As Long) As Long: Score = Scores(Rank).Score: End Property
Public Property Let Score(ByVal Rank As Long, ByVal Value As Long): Scores(Rank).Score = Value: End Property

Public Property Get Count() As Long: Count = UBound(Scores) + 1: End Property
Public Property Let Count(ByVal Length As Long)
    ReDim Scores(Length - 1) As PM_SCORE
End Property

'====================================================================================
'Load
'====================================================================================
Public Function Load(ByVal ID As String) As Boolean
    'If an error occurs loading, this function will return False
    Load = False: On Local Error GoTo LblExit
    
    Dim FileNumber As Long
    FileNumber = FreeFile
    
    Dim AppData As String
    AppData = SharedAPI.GetSpecialFolder(CSIDL_APPDATA)
    If Dir(AppData & "Camen Design", vbDirectory) = "" Then
        'Create the Camen Design folder in Application Data
        MkDir AppData & "Camen Design"
    End If
    If Dir(AppData & "Camen Design\Pac Mar", vbDirectory) = "" Then
        'Create the Pac Mar folder in Application Data
        MkDir AppData & "Camen Design\Pac Mar"
    End If
    'Read in the local dat file
    Dim FilePath
    FilePath = AppData & "Camen Design\Pac Mar\" & ID & ".bdat"
    
    Open FilePath For Binary Access Read As #FileNumber
    Load = Me.Read(FileNumber)
    If Load Then Me.FilePath = FilePath
    
LblExit:
    Close #FileNumber
End Function

'====================================================================================
'Read: Load data from an already opened file handle
'====================================================================================
Public Function Read(ByVal UseFileNumber As Long) As Boolean
    Read = False: On Local Error GoTo LblExit
    
    'The first thing is the file format version
    Dim FileTypeVersion As Single
    Get #UseFileNumber, , FileTypeVersion
    'Get the scores
    Get #UseFileNumber, , Scores
    Read = True
    
LblExit:
End Function

'====================================================================================
'Save
'====================================================================================
Public Function Save(Optional ByVal UseFileNumber As Long = 0) As Long
    'If an error occurs saving, this function will return False
    Save = False: On Local Error GoTo LblExit
    
    'If handed a file number, append to that file. This is used to embed high scores
    'into level files so that people can share the levels they make and the scores
    'earnt on the level persist
    Dim FileNumber As Long
    If UseFileNumber = 0 Then
        FileNumber = 1
        Open FilePath For Binary Access Write As #FreeFile
    Else
        FileNumber = UseFileNumber
    End If
    
    'Save the score table data
    Put #FileNumber, , CSng(1.2)  'File format version
    Put #FileNumber, , Scores     'Write the scores
    Save = True
    
LblExit:
    On Local Error Resume Next
    If UseFileNumber > 0 Then Close #FileNumber
End Function

'====================================================================================
'Insert: Add your score to a score table
'====================================================================================
Public Function Insert(ByVal Score As Long, ByVal GhostsEaten As Long, ByVal TimeTaken As Long, Optional ByVal RankBy As PM_RANKBY = PM_RANKBY_SCORE) As Long
    Dim K As Long
    
    'Calculate your Rank
    Insert = Rank(Score, TimeTaken, RankBy)
    
    'If you ranked in the table
    If Insert > -1 Then
        'Move all the slots down one to fit you in
        For K = UBound(Scores) To Insert + 1 Step -1
           Scores(K).Ghosts = Scores(K - 1).Ghosts
           Scores(K).Name = Scores(K - 1).Name
           Scores(K).Score = Scores(K - 1).Score
           Scores(K).Time = Scores(K - 1).Time
        Next K
        'Insert your score and details
        With Scores(Insert)
           .Ghosts = GhostsEaten
           .Name = "   "
           .Score = Score
           .Time = TimeTaken
        End With
    End If
End Function

Public Function Rank(ByVal Score As Long, ByVal TimeTaken As Long, Optional ByVal RankBy As PM_RANKBY = PM_RANKBY_SCORE) As Long
    Rank = -1
    If Score = 0 Then Exit Function
    
    Dim K As Long
    For K = 0 To UBound(Scores)
        'Is your score equal or higher? (or Time less than or equal)
        If (RankBy = PM_RANKBY_SCORE And Score >= Scores(K).Score) Or _
           (RankBy = PM_RANKBY_TIME And (TimeTaken <= Scores(K).Time Or Scores(K).Time = 0)) _
        Then
            'If there were many of the same score, the least or equal time wins
            '(or if there were many of the same time, the higher or equal score wins)
            If (RankBy = PM_RANKBY_SCORE And (TimeTaken <= Scores(K).Time Or Scores(K).Time = 0)) Or _
               (RankBy = PM_RANKBY_TIME And Score >= Scores(K).Score) _
            Then
                'You take this slot!
                Rank = K: Exit For
            End If
        End If
    Next K
End Function

Private Sub Class_Terminate()
    Erase Scores
End Sub
